
/**
 *	\file
 *	Defines the sun::application base class.
 *	\author Sean Tromnas
 */

#ifndef	SUN_APPLICATION_HPP
#define	SUN_APPLICATION_HPP

#include <sun/entry_point/user_entry_point.hpp>
#include <sun/game_state/game_state_fwd.hpp>
#include <rainbow/viewport/viewport_stack.hpp>
#include <sun/lua/lua_fwd.hpp>
#include <boost/noncopyable.hpp>

namespace sun
{

	/**
	 *	Base application helper class for sun.
	 *	Manages the creation/destruction of required system components and the main game loop.
	 *	\author Sean Tromans
	 */
	class	application	: private boost::noncopyable
	{
		//
		//	Public Member Functions
		//
		public:

			/**
			 *	Initialises the application, begins the main game loop and the destroys the application.
			 *	All game components required by sun are managed by this base class.
			 *	@param command_line The command line arguments sent into the application.
			 *	\author Sean Tromans
			 */
			void	run( sun::command_line_type const & command_line );

		//
		//	Protected Member Functions
		//
		protected:

			/**
			 *	Constructor for the application object.
			 *	Protected to prevent instantiation.
			 *	@param step_time The length of time between each logic step.
			 *	@param max_steps_per_iteration The maximum number of steps the application can make each iteration. Used to prevent near-infinite loops between stalls in the game.
			 *	\author Sean Tromans
			 */
			application( float step_time = 1.0f / 60.0f, size_t max_steps_per_iteration = 5 );

			/**
			 *	User call back to initialise the application window and push the initial game state.
			 *	@param command_line The command line arguments sent into the application.
			 *	@return false if the application could not be begun.
			 *	\author Sean Tromans
			 */
			virtual bool begin_application( sun::command_line_type const & command_line ) = 0;

			/**
			 *	User callback to initialise the game specific Lua interface.
			 *	@param L The Lua state being initialised.
			 *	@return false if the interface could not be created.
			 *	\author Sean Tromans
			 */
			virtual bool initialise_lua_interface( lua_State * L ) = 0;

			/**
			Quits the game loop and destroys the application.
			\author Sean Tromans
			*/
			void exit( );

		//
		//	Private Member Functions
		//
		private:

			/**
			 *	Initialises the required sun components and calls begin_application.
			 *	@param command_line The command line arguments sent into the application.
			 *	@return false if the application failed to initialise.
			 *	\author Sean Tromans
			 */
			bool initialise( sun::command_line_type const & command_line );

			/**
			 *	Runs the main game loop at the desired step rate.
			 *	\author Sean Tromans
			 */
			void loop( );

			/**
			 *	Destroys the sun components created in initialise.
			 *	\author Sean Tromans
			 */
			void destroy( );

		//
		//	Protected Member Variables
		//
		protected:

			state_ptr	m_state;	///< The currently running game state. An implementation should assign to this during \c begin_application.

		//
		//	Private Member Variables
		//
		private:

			float		m_step_time;				///< The time between each game logic step.
			size_t		m_max_steps_per_iteration;	///< The maximum number of steps to perform per draw.
			bool		m_running;					///< Whether the game is still running.

			rainbow::viewport_stack	m_viewport_stack;	///< The viewport stack to use for drawing each frame.

		//
		//	Static Member Functions
		//
		public:

			/**
			Exposes the application to lua.
			@param  L The lua_State being initialised.
			\author Sean Tromans
			*/
			static void lua_interface( lua_State * L );
	};

};

#endif	//SUN_APPLICATION_HPP
